package org.stone.project.logInterface.aop;

import cn.hutool.core.util.ObjectUtil;
import cn.hutool.json.JSONUtil;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.core.annotation.Order;
import org.springframework.http.HttpMethod;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.stone.project.common.pojo.annotation.LogRequest;
import org.stone.project.common.pojo.constant.AopExecOrder;
import org.stone.project.common.utils.RequestIdUtil;
import org.stone.project.logInterface.pojo.po.RequestLog;
import org.stone.project.logInterface.service.RequestPathService;
import org.stone.project.logInterface.utils.LogUtil;

import java.lang.annotation.Annotation;

@Aspect
@Component
@Order(value = AopExecOrder.REQUEST_LOG_ORDER)
@ConditionalOnProperty(name = "logging.aop.request.enabled",havingValue = "true", matchIfMissing = false)
public class RequestLogAop {
    @Autowired(required = false)
    private RequestPathService requestPathService;


    /**
     * 接口日志
     * @param joinPoint
     * @param logRequest
     * @return
     */
    @Around(value = "@annotation(logRequest)")
    public Object addLogRequest(ProceedingJoinPoint joinPoint, LogRequest logRequest){
        String requestType = "OTHER";
        {
            MethodSignature signature = (MethodSignature) joinPoint.getSignature();
            Annotation[] annotations = signature.getMethod().getAnnotations();
            for (Annotation annotation : annotations) {
                if (annotation instanceof GetMapping){
                    requestType = HttpMethod.GET.name();
                }else if (annotation instanceof PostMapping){
                    requestType = HttpMethod.POST.name();
                }else if (annotation instanceof PutMapping){
                    requestType = HttpMethod.PUT.name();
                }
                else if (annotation instanceof DeleteMapping){
                    requestType = HttpMethod.DELETE.name();
                }
            }
        }

        //获取参数
        Object[] args = joinPoint.getArgs();
        RequestLog requestLog = new RequestLog();
        requestLog.setRequestType(requestType);
        requestLog.setRequestId(RequestIdUtil.getRequestId());
        if (logRequest.recordRequestId() && ObjectUtil.isNotNull(requestPathService)){
            requestLog.setPath(requestPathService.getRequestPath());
        }
        if (logRequest.recordRequestParam() && ObjectUtil.isNotNull(joinPoint.getArgs())){
            requestLog.setRequestParam(JSONUtil.toJsonStr(joinPoint.getArgs()));
        }
        try {
            Object proceed = joinPoint.proceed(args);
            if (logRequest.recordRequestResponse() && ObjectUtil.isNotNull(proceed)){
                requestLog.setResponseBody(JSONUtil.toJsonStr(proceed));
            }
            return proceed;
        } catch (Throwable e) {
            throw new RuntimeException(e);
        }finally {
            LogUtil.addReuqestLog(requestLog);
        }
    }
}
